package org.micode.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;

@Slf4j
public class DateUtils {

    public static final String DATE_FORMAT_MILLISECOND_STRING = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DATE_FORMAT_SECOND_STRING = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT_MONTH_STRING = "yyyy-MM";
    public static final String DATE_FORMAT_STRING = "yyyy-MM-dd";
    public static final String YYYYMMDD_STRING = "yyyyMMdd";
    public static final String YYYYMM_STRING = "yyyyMM";
    public static final String YYYYMMDDHHMMSS_STRING = "yyyyMMddHHmmss";

    /**
     * 验证字符串是否为指定日期格式
     * @param oriDateStr 待验证字符串
     * @return 有效性结果, true 为正确, false 为错误
     */
    public static boolean dateTimeMsStrIsValid(String oriDateStr) {
        return dateStrIsValid(oriDateStr, DATE_FORMAT_MILLISECOND_STRING);
    }

    /**
     * 验证字符串是否为指定日期格式
     * @param oriDateStr 待验证字符串
     * @param pattern 日期字符串格式, 例如 "yyyy-MM-dd"
     * @return 有效性结果, true 为正确, false 为错误
     */
    public static boolean dateStrIsValid(String oriDateStr, String pattern) {
        if (StringExtUtils.isAnyEmpty(oriDateStr) || StringExtUtils.isAnyEmpty(pattern)) {
            return false;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);

        try {
            Date date = dateFormat.parse(oriDateStr);
            return oriDateStr.equals(dateFormat.format(date));
        } catch (ParseException e) {
            return false;
        }
    }

    public static boolean isValidDate(String str) {
        if (org.springframework.util.StringUtils.isEmpty(str)) {
            return false;
        }
        boolean convertSuccess = true;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            convertSuccess = false;
        }
        return convertSuccess;
    }

    public static Integer yyyymm(Date inDate) {
        if (inDate != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(inDate);
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH) + 1;
            return year * 100 + month;
        }
        return null;
    }

    public static Date zeroHourForDate(Date inDate) {
        if (inDate != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(inDate);
            calendar.set(Calendar.HOUR, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            return calendar.getTime();
        }
        return null;
    }

    public static String currentTimeString() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_MILLISECOND_STRING);
        Calendar calendar = Calendar.getInstance();
        return dateFormat.format(calendar.getTime());
    }

    public static String currentDatetimeString() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_SECOND_STRING);
        Calendar calendar = Calendar.getInstance();
        return dateFormat.format(calendar.getTime());
    }

    public static String strYYYYMMDD() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(YYYYMMDD_STRING);
        Calendar calendar = Calendar.getInstance();
        return dateFormat.format(calendar.getTime());
    }

    public static String strYYYYMMDDHHMMSS(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(YYYYMMDDHHMMSS_STRING);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return dateFormat.format(calendar.getTime());
    }

    /**
     * 按照参数format的格式，日期转字符串
     *
     * @param date   要转换的日期
     * @param format 转换格式
     * @return 转换结果字符串
     */
    public static String date2Str(Date date, String format) {
        if (date != null) {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(date);
        } else {
            return "";
        }
    }

    public static String date2Str(Date date) {
        if (date != null) {
            SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_STRING);
            return sdf.format(date);
        } else {
            return "";
        }
    }

    /**
     * 把日期的时间设置为 0
     *
     * @param value
     * @return
     */
    public static Date zeroTimeForDate(Date value) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(value);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Calendar zeroTimeForCalendar(Date value) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(value);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
    }

    public static Integer date2YYYYMMDD(Date date) {
        if (date != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            return Integer.parseInt(sdf.format(date));
        } else {
            return null;
        }
    }

    public static Integer date2YYYYMM(Date date) {
        if (date != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
            return Integer.parseInt(sdf.format(date));
        } else {
            return null;
        }
    }

    public static Date str2Date(String dateStr) {
        if (dateStr != null) {
            SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_STRING);
            try {
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                return null;
            }
        } else {
            return null;
        }
    }

    public static LocalDate str2LocalDate(String dateStr) {
        return LocalDate.parse(dateStr);
    }

    public static LocalDateTime str2LocalDateTime(String dateStr) {
        return LocalDateTime.parse(dateStr);
    }

    public static Date str2Date(String dateStr, String format) {
        if (dateStr != null) {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            try {
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                return null;
            }
        } else {
            return null;
        }
    }

    public static Long stringToTimestamp(String strDatetime) throws ParseException {
        if (org.springframework.util.StringUtils.isEmpty(strDatetime)) {
            return null;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_MILLISECOND_STRING);
        return dateFormat.parse(strDatetime).getTime();
    }

    /**
     * yyyy-MM-dd HH:mm:ss
     *
     * @param strDatetime
     * @return
     * @throws ParseException
     */
    public static Date stringToDatetime(String strDatetime) {
        if (org.springframework.util.StringUtils.isEmpty(strDatetime)) {
            return null;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_SECOND_STRING);
        try {
            return dateFormat.parse(strDatetime);
        } catch (ParseException e) {
            log.warn("dateFormat.parse() call failed, {}", e.getMessage());
            return new Date();
        }
    }

    /**
     * yyyy-MM-dd HH:mm:ss
     *
     * @param msDatetime
     * @return
     * @throws ParseException
     */
    public static Date stringToDatetimeMS(String msDatetime) {
        if (StringUtils.isEmpty(msDatetime)) {
            return null;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_MILLISECOND_STRING);
        try {
            return dateFormat.parse(msDatetime);
        } catch (ParseException e) {
            log.warn("dateFormat.parse() call failed, {}", e.getMessage());
            return new Date();
        }
    }

    public static Date afterSecond(int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.SECOND, seconds);
        return calendar.getTime();
    }

    /**
     * 一年之后
     *
     * @return
     */
    public static Date afterOneYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        // calendar.add(calendar.DAY_OF_YEAR, 1);//增加一天,负数为减少一天
        // calendar.add(calendar.DAY_OF_MONTH, 1);//增加一天
        // calendar.add(calendar.DATE,1);//增加一天
        // calendar.add(calendar.WEEK_OF_MONTH, 1);//增加一个礼拜
        // calendar.add(calendar.WEEK_OF_YEAR,1);//增加一个礼拜

        // 把日期往后增加一年.整数往后推,负数往前移动
        calendar.add(calendar.YEAR, 1);
        return calendar.getTime();
    }

    public static Date afterSomeDay(int dayAmount) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        calendar.add(calendar.DATE, dayAmount);//增加一天

        return calendar.getTime();
    }

    public static Date yesterday() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, -24);
        return calendar.getTime();
    }

    public static Date nextDate(Date theDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(theDate);

        calendar.add(calendar.DATE, 1);//增加一天

        return calendar.getTime();
    }

    public static Date monthFirstDate(Date theDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(theDate);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1); //设置为1号,当前日期既为本月第一天
        return calendar.getTime();
    }

    public static Date nextMonthFirstDate(Date theDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(theDate);
        calendar.set(Calendar.DAY_OF_MONTH, 1); //设置为1号,当前日期既为本月第一天
        calendar.add(Calendar.MONTH, 1);
        return calendar.getTime();
    }

    public static String monthFirstDateStr(Date theDate) {
        Date firstDate = monthFirstDate(theDate);
        return date2Str(firstDate, "yyyy-MM-dd");
    }

    public static String nextMonthFirstDateStr(Date theDate) {
        Date firstDate = nextMonthFirstDate(theDate);
        return date2Str(firstDate, "yyyy-MM-dd");
    }

    public static void main(String[] args) {
//        LocalDateTime.now().toEpochSecond();
        System.out.println(str2LocalDateTime("2022-10-08"));
    }

}
